package cn.lg.soar.database.base.controller;

import cn.lg.soar.common.model.HttpResult;
import cn.lg.soar.common.model.PageQuery;
import cn.lg.soar.common.model.PageResult;
import cn.lg.soar.common.util.AssertUtil;
import cn.lg.soar.common.util.BeanCopier;
import cn.lg.soar.common.util.ParameterUtil;
import cn.lg.soar.core.util.easyexcel.ExcelUtil;
import cn.lg.soar.database.query.QueryParams;
import cn.lg.soar.database.query.SqueryWapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 基础控制器
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public abstract class BaseController<T, S extends IService<T>> {

    protected S service;

    private Class<T> entityClass;

    protected abstract Serializable getId(T entity);

    @Autowired
    public void setService(S service) {
        this.service = service;
        this.entityClass = service.getEntityClass();
    }

    private SqueryWapper<T> squeryWapper;

    /**
     * 创建
     * @param data
     * @return
     */
    protected HttpResult<Serializable> createResult(T data) {
        ParameterUtil.notNull(data, "数据不能为空");
        AssertUtil.isTrue(service.save(data), "创建失败");
        return HttpResult.<Serializable>success("创建成功").setData(getId(data));
    }

    /**
     * 更新
     * @param data
     * @return
     */
    protected HttpResult<Void> updateResult(T data) {
        ParameterUtil.notNull(data, "数据不能为空");
        AssertUtil.isTrue(service.updateById(data), "更新失败");
        return HttpResult.success("更新成功");
    }

    /**
     * 删除
     * @param ids
     * @return
     */
    protected HttpResult<Void> removeResult(List<? extends Serializable> ids) {
        ParameterUtil.notEmpty(ids, "缺少要删除的数据id");
        AssertUtil.isTrue(service.removeByIds(ids), "删除失败");
        return HttpResult.success("删除成功");
    }

    /**
     * 详情
     * @param id
     * @return
     */
    protected <E>HttpResult<E> detailResult(Serializable id, Class<E> eClass) {
        ParameterUtil.notNull(id, "缺少数据id");
        T data = service.getById(id);
        ParameterUtil.notNull(data, "数据不存在", id);
        return HttpResult.data(
                BeanCopier.createCacheable(entityClass, eClass)
                        .convert(data)
        );
    }

    /**
     * 详情
     * @param id
     * @return
     */
    protected HttpResult<T> detailResult(Serializable id) {
        ParameterUtil.notNull(id, "缺少数据id");
        T data = service.getById(id);
        ParameterUtil.notNull(data, "数据不存在", id);
        return HttpResult.data(data);
    }

    /**
     * 查询（分页）
     * @param page
     * @param params
     * @return
     */
    protected HttpResult<PageResult<T>> queryResult(PageQuery page, QueryParams params){
        return HttpResult.data(
                getPage(page, params)
        );
    }

    /**
     * 查询（分页）,翻译转换
     * @param page
     * @param params
     * @param eClass
     * @param <E>
     * @return
     */
    protected <E>HttpResult<PageResult<E>> queryResult(PageQuery page, QueryParams params, Class<E> eClass){
        return HttpResult.data(
                getPage(page, params, eClass)
        );
    }

    /**
     * 统计总数
     * @param params
     * @return
     */
    protected HttpResult<Long> countResult(QueryParams params){
        if (squeryWapper == null) {
            squeryWapper = new SqueryWapper<>(entityClass);
        }
        QueryWrapper<T> wrapper = Wrappers.query();
        squeryWapper.setWhere(params.getF(), wrapper);
        return HttpResult.data(
                service.count(wrapper)
        );
    }

    /**
     * 是否存在
     * @param params
     * @return
     */
    protected HttpResult<Boolean> existResult(QueryParams params){
        if (squeryWapper == null) {
            squeryWapper = new SqueryWapper<>(entityClass);
        }
        QueryWrapper<T> wrapper = Wrappers.query();
        squeryWapper.setWhere(params.getF(), wrapper);

        wrapper.select("1");
        IPage<T> page = new Page<>(0, 1, false);
        return HttpResult.data(
                this.service.page(page, wrapper).getRecords().size() == 1
        );
    }

    /**
     * 导出excel
     * @param filename 导出文件名
     * @param params 查询参数
     * @param resp 响应
     */
    protected void exportExcel(String filename, QueryParams params, HttpServletResponse resp){
        // 查询数据
        List<T> list = getList(params);
        // 导出
        ExcelUtil.exportExcel(filename, list, resp);
    }

    /**
     * 导出
     * @param filename
     * @param params
     * @param resp
     * @param eClass 导出数据类型
     * @param <E>
     */
    protected <E>void exportExcel(String filename, QueryParams params, HttpServletResponse resp, Class<E> eClass){
        // 查询数据
        List<E> list = getList(params, eClass);
        // 导出
        ExcelUtil.exportExcel(filename, list, resp);
    }

    /**
     * excel导入
     * @param req
     * @return
     */
    protected HttpResult<Void> importExcel(HttpServletRequest req) {
        // 读取数据
        List<T> list = ExcelUtil.importExcel(req, this.entityClass);
        // 保存数据
        AssertUtil.isTrue(service.saveBatch(list), "导入失败");
        return HttpResult.success("导入成功");
    }

    /**
     * 导入
     * @param req
     * @param eClass 导入数据类型
     * @param <E>
     * @return
     */
    protected <E>HttpResult<Void> importExcel(HttpServletRequest req, Class<E> eClass){
        // 读取数据
        List<E> list = ExcelUtil.importExcel(req, eClass);
        // 转换
        List<T> data = BeanCopier.createCacheable(eClass, entityClass)
                .convertBatch(list)
                .collect(Collectors.toList());
        // TODO 反翻译

        // 保存数据
        AssertUtil.isTrue(service.saveBatch(data), "导入失败");
        return HttpResult.success("导入成功");
    }

    /**
     * 查询（分页），增加翻译处理
     * @param page
     * @param params
     * @param eClass 转换翻译类型
     * @param <E>
     * @return
     */
    protected <E>PageResult<E> getPage(PageQuery page, QueryParams params, Class<E> eClass){
        PageResult<T> pageResult = getPage(page, params);
        return pageResult.convert(eClass);
    }

    /**
     * 分页查询
     * @param page
     * @param params
     * @return
     */
    protected PageResult<T> getPage(PageQuery page, QueryParams params){
        if (squeryWapper == null) {
            squeryWapper = new SqueryWapper<>(entityClass);
        }
        return squeryWapper.query(service, page, params);
    }

    /**
     * 查询
     * @param params
     * @return
     */
    protected List<T> getList(QueryParams params) {
        if (squeryWapper == null) {
            squeryWapper = new SqueryWapper<>(entityClass);
        }
        QueryWrapper<T> wrapper = Wrappers.query();
        squeryWapper.setWhere(params.getF(), wrapper);
        squeryWapper.setSelect(params.getF(), wrapper);
        squeryWapper.setOrderBy(params.getF(), wrapper);
        return service.list(wrapper);
    }

    /**
     * 查询，翻译
     * @param params
     * @return
     */
    protected <E>List<E> getList(QueryParams params, Class<E> eClass) {
        List<T> list = getList(params);
        return BeanCopier.createCacheable(entityClass, eClass)
                .convertBatch(list)
                .collect(Collectors.toList());
    }

}
